﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Forms;
//using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace EXEStart
{
    ///
    public struct ListIcon
    {
        public Icon iconLarge;
        public Icon iconNormal;
        public Icon iconSmall;
    }

    public partial class FrmMain : Form
    {

        List<GameItem.ItemInfo> ExeItems = new();

        bool isEdited = false;

        ///
        private readonly string sJSONfile = Path.GetDirectoryName(Application.ExecutablePath) + @"\data.json";

        private Cursor Handcursor = null;

        private FormWindowState windowState = FormWindowState.Normal;

        public FrmMain()
        {
            InitializeComponent();
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            this.Visible = false;
            this.Icon = GetFileIcon.GetIcon(Application.ExecutablePath); //global::EXEStart.Properties.Resources.Game;

            imgListLarge.ImageSize = new Size(96, 96);
            lstViewDB.LargeImageList = imgListLarge;
            imgList.ImageSize = new Size(48, 48);
            imgListSmall.ImageSize = new Size(32, 32);

            lblApull.Text = $"www.apull.net";

            picIcon.Image = this.Icon.ToBitmap();
            labCaption.Text = Program.msgTitle;

            GetItemFromJson(sJSONfile);
            showCount();

            this.Visible = true;
            Handcursor = GetCursor();
        }

        private Cursor GetCursor()
        {
            Cursor cursor = Cursor.Current;
            try
            {
                cursor = new Cursor(Properties.Resources.Hand.GetHicon());
            }
            catch(Exception)
            {
                cursor = Cursor.Current;
            }
            return cursor;
        }

        #region 移动窗体

        bool mouseState = false;
        Point mousePoint;
        private void FrmMain_MouseDown(object sender, MouseEventArgs e)
        {
            mouseState = true;
            mousePoint = e.Location;
        }

        private void FrmMain_MouseMove(object sender, MouseEventArgs e)
        {
            if(mouseState && e.Button == MouseButtons.Left && this.WindowState != FormWindowState.Maximized)
            {
                this.Left += e.X - mousePoint.X;
                this.Top += e.Y - mousePoint.Y;
            }
        }

        private void FrmMain_MouseUp(object sender, MouseEventArgs e)
        {
            mouseState = false;
        }

        #endregion


        #region 添加项目

        /// <summary>
        /// 从JSON文件读取列表信息
        /// </summary>
        /// <param name="jsonPath">JSON文件路径</param>
        private void GetItemFromJson(string jsonPath)
        {
            string message = GameItem.ReadItemsFromJson(jsonPath, ref ExeItems);

            if(message != String.Empty)
            {
                MessageBox.Show($"读取失败！\n\n{message}", Program.msgTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            foreach(var itemInfo in ExeItems)
            {
                if(!string.IsNullOrEmpty(itemInfo.image))
                {
                    itemInfo.ImageICO = GameItem.Base64ToImg(itemInfo.image);
                }

                if(itemInfo.ImageICO == null)
                {
                    //ListIcon imgs = GetListIcons(itemInfo.path);
                    Icon ico = GetFileIcon.GetIcon(itemInfo.path, 0, IconSize.Jumbo);
                    //itemInfo.ImageICO=imgs.iconLarge.ToBitmap();
                    if(ico != null)
                    {
                        itemInfo.ImageICO = ico.ToBitmap();
                        GetFileIcon.DestroyIcon(ico.Handle);
                    }
                    else
                        itemInfo.ImageICO = this.Icon.ToBitmap();
                    itemInfo.image = GameItem.imgToBase64(itemInfo.ImageICO);
                }

                itemInfo.ImageICO.Tag = itemInfo.name;

                AddItemToListView(itemInfo);
            }
        }

        /// <summary>
        /// 插入项目到ListView中
        /// </summary>
        /// <param name="itemInfo">程序信息</param>
        /// <param name="index">插入位置索引，-1插入到最后</param>
        private ListViewItem AddItemToListView(GameItem.ItemInfo itemInfo, int index = -1)
        {

            imgListLarge.Images.Add(itemInfo.ImageICO);
            imgList.Images.Add(itemInfo.ImageICO);
            imgListSmall.Images.Add(itemInfo.ImageICO);

            ListViewItem item = new()
            {
                //string tag = $"{itemInfo.path}|{itemInfo.args}|{itemInfo.windowsSytle}|{itemInfo.workingDir}";
                Text = itemInfo.name,
                ImageIndex = imgList.Images.Count - 1,
                Tag = $"{itemInfo.windowsSytle}",
                ToolTipText = $"{Path.GetFileName(itemInfo.path)}\n位置：{Path.GetDirectoryName(itemInfo.path)}"
            };
            item.SubItems.AddRange(new string[] { itemInfo.path, itemInfo.args, itemInfo.workingDir });

            if(index != -1)
            {
                lstViewDB.Items.Insert(index, item);
            }
            else
                lstViewDB.Items.Add(item);

            return item;
        }

        /// <summary>
        /// 修改选中项
        /// </summary>
        /// <param name="info">修改内容</param>
        /// <param name="item">要修改的ListView项</param>
        private void EditListViewItem(GameItem.ItemInfo itemInfo, ListViewItem item)
        {
            if(item == null) return;
            item.SubItems.Clear();

            item.Text = itemInfo.name;
            item.Tag = $"{itemInfo.windowsSytle}";
            item.ToolTipText = $"{Path.GetFileName(itemInfo.path)} 位置：{Path.GetDirectoryName(itemInfo.path)}";
            item.SubItems.AddRange(new string[] { itemInfo.path, itemInfo.args, itemInfo.workingDir });

            Image img = GameItem.Base64ToImg(itemInfo.image);
            int imgIndex = item.ImageIndex;

            Image resizeImg = GetFileIcon.ResizeImage(img, 96);
            string imgbase = GameItem.imgToBase64(resizeImg);
            if(imgbase != null && imgbase != itemInfo.image)
            {
                imgList.Images[imgIndex] = GetFileIcon.ResizeImage(img, 48);
                imgListLarge.Images[imgIndex] = img.Width > 96 ? resizeImg : img;
                imgListSmall.Images[imgIndex] = GetFileIcon.ResizeImage(img, 32);

                itemInfo.image = imgbase;
            }
            img.Dispose();
            resizeImg.Dispose();

            lstViewDB.Refresh();

            GC.Collect();
        }

        /// <summary>
        /// 从exe文件获取多个尺寸图标
        /// </summary>
        /// <param name="sFileName">exe文件路径</param>
        /// <returns>获取到的个图标</returns>
        private ListIcon GetListIcons(string sFileName, int index = 0)
        {
            //处理图标
            ListIcon icons = new();
            icons.iconLarge = GetFileIcon.GetIcon(sFileName, index, IconSize.Jumbo);
            icons.iconNormal = GetFileIcon.GetIcon(sFileName, index, IconSize.Large);
            icons.iconSmall = GetFileIcon.GetIcon(sFileName, index, IconSize.Norma);

            if(icons.iconLarge == null)
            {
                icons.iconLarge = GetFileIcon.GetIconByFileType(Path.GetExtension(sFileName).ToLower(), IconSize.Jumbo);
                if(icons.iconLarge == null)
                    icons.iconLarge = (Icon)this.Icon.Clone();
            }

            if(icons.iconNormal == null)
            {
                icons.iconNormal = GetFileIcon.GetIconByFileType(Path.GetExtension(sFileName).ToLower(), IconSize.Large);
                if(icons.iconNormal == null)
                    icons.iconNormal = (Icon)icons.iconLarge.Clone();
            }

            if(icons.iconSmall == null)
                icons.iconSmall = (Icon)icons.iconNormal.Clone();

            return icons;
        }

        /// TODO: 更改判断
        /// <summary>
        /// 添加图标到ImageList
        /// </summary>
        /// <param name="icons">要添加的图标</param>
        private void AddToImgList(ListIcon icons)
        {
            if(icons.iconLarge != null || icons.iconNormal != null || icons.iconSmall != null)
            {
                imgListLarge.Images.Add(icons.iconLarge);
                imgList.Images.Add(icons.iconNormal);
                imgListSmall.Images.Add(icons.iconSmall);

                GetFileIcon.DestroyIcon(icons.iconLarge.Handle);
                GetFileIcon.DestroyIcon(icons.iconNormal.Handle);
                GetFileIcon.DestroyIcon(icons.iconSmall.Handle);
            }
        }

        /// <summary>
        /// 从ImageList删除指定索引的图标
        /// </summary>
        /// <param name="index">要删除图标索引</param>
        private void DelFromImgList(int index)
        {
            imgListLarge.Images[index].Dispose();
            imgListLarge.Images.RemoveAt(index);

            imgList.Images[index].Dispose();
            imgList.Images.RemoveAt(index);

            imgListSmall.Images[index].Dispose();
            imgListSmall.Images.RemoveAt(index);
        }

        /// <summary>
        /// 查找重复程序
        /// </summary>
        /// <param name="sFileName">要查找的程序文件名</param>
        /// <param name="strName">返回已存在名称</param>
        /// <returns>返回已存在索引，没有重复返回-1</returns>
        private int FindGame(string sFileName, ref string strName)
        {
            foreach(ListViewItem item in lstViewDB.Items)
            {
                if(item.SubItems[1].Text == sFileName)
                {
                    strName = item.Text;
                    return item.Index;
                }
            }
            return -1;
        }

        //显示游戏统计
        private void showCount()
        {
            if(lstViewDB.Items.Count > 0)
                lblCount.Text = $"已添加{lstViewDB.Items.Count}个游戏";
            else
                lblCount.Text = $"无游戏，请添加！";
        }

        /// <summary>
        /// 添加程序到列表
        /// </summary>
        /// <param name="sFileName">要添加的文件路径</param>
        /// <param name="name">要显示的名字</param>
        /// <param name="itemIndex">添加位置索引，-1添加到末尾</param>
        private void AddItem(string sFileName, string name = "", int itemIndex = -1)
        {
            //处理文件名
            string ext = Path.GetExtension(sFileName).ToLower();
            string fName = Path.GetFileNameWithoutExtension(sFileName);

            ExeArg exeArg = new(sFileName);
            if(!exeArg.isExe())
            {
                MessageBox.Show($"'{fName}{exeArg.TargetExt}' 添加失败！\n\n不支持的文件类型。\n允许添加文件类型：.exe、.lnk、.bat、.cmd\n", exeArg.TargetPath, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if(!File.Exists(exeArg.TargetPath))
            {
                MessageBox.Show($"'{fName}' 添加失败！\n\n目标文件不存在！\n'{exeArg.TargetPath}' ", exeArg.TargetPath, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            int index = FindGame(exeArg.TargetPath, ref fName);
            if(index != -1)
            {
                MessageBox.Show($"'{fName}' 添加失败！\n\n该程序已存在！", exeArg.TargetPath, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                lstViewDB.Items[index].Selected = true;
                lstViewDB.EnsureVisible(index); //定位到该项

                return;
            }

            //处理图标
            ListIcon icons = GetListIcons(exeArg.IconLocation, exeArg.IcoIndex);
            //AddToImgList(icons);

            Image img = icons.iconLarge.ToBitmap();
            Image resizeImg = GetFileIcon.ResizeImage(img, 96);

            GameItem.ItemInfo iteminfo = new GameItem.ItemInfo()
            {
                name = exeArg.Name,
                args = exeArg.Arguments,
                image = GameItem.imgToBase64(resizeImg),
                id = ExeItems.Count,
                path = exeArg.TargetPath,
                windowsSytle = exeArg.WindowStyle,
                workingDir = exeArg.WorkingDirectory,
                ImageICO = resizeImg
            };

            iteminfo.ImageICO.Tag = iteminfo.name;

            //添加列表项
            ListViewItem item = AddItemToListView(iteminfo);
            ExeItems.Add(iteminfo);

            item.Selected = true;
            lstViewDB.EnsureVisible(item.Index);
            showCount();
        }

        /// <summary>
        /// 批量添加程序
        /// </summary>
        /// <param name="sFiles">要添加的文件名</param>
        /// <param name="sPath">文件路径，文件名不包含路径，则必须设置该值</param>
        private void AddFiles(string[] sFiles, string path = "")
        {
            if(sFiles.Length == 0)
                return;

            string file = "";
            foreach(string str in sFiles)
            {
                file = (path == "") ? str : Path.Combine(path, str);
                AddItem(file);
            }
        }

        /// <summary>
        /// 获取列表项参数信息
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private GameItem.ItemInfo getInfoFromItem(ListViewItem item)
        {
            GameItem.ItemInfo itemInfo = new GameItem.ItemInfo()
            {
                id = item.Index,
                name = item.Text,
                path = item.SubItems[1].Text,
                args = item.SubItems[2].Text,
                workingDir = item.SubItems[3].Text,
                windowsSytle = int.TryParse(item.Tag.ToString(), out int _) ? int.Parse(item.Tag.ToString()) : 0,
                image = GameItem.imgToBase64(imgListLarge.Images[item.ImageIndex]),
                ImageICO = imgListLarge.Images[item.ImageIndex],
            };

            return itemInfo;
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDlg = new OpenFileDialog()
            {
                DereferenceLinks = false,
                Title = "选择exe文件",
                Filter = "程序文件(*.exe;*.cmd;*.bat)|*.exe;*.cmd;*.bat",
                Multiselect = true,
                InitialDirectory = ".",
            };

            if(openFileDlg.ShowDialog() != DialogResult.OK)
                return;

            string[] fileNames = openFileDlg.SafeFileNames;
            if(fileNames.Length == 0)
                return;

            string path = Path.GetDirectoryName(openFileDlg.FileName);
            AddFiles(fileNames, path);

            setSaveStatus();
        }

        #endregion 添加项目

        private void btnSave_Click(object sender, EventArgs e)
        {
            /* List<GameItem.ItemInfo> items = new();

             foreach(ListViewItem item in lstViewDB.Items)
             {
                 GameItem.ItemInfo iteminfo = getInfoFromItem(item);

                 if(item.Index >= imgList.Images.Count)
                     iteminfo.image = "";

                 items.Add(iteminfo);
             }*/

            string message = GameItem.SaveItemsToJson(sJSONfile, ExeItems);
            bool isOK = (message == String.Empty);

            MessageBox.Show(isOK ? "保存成功！\n\n" : $"保存失败！\n\n{message}", Program.msgTitle, MessageBoxButtons.OK, isOK ? MessageBoxIcon.Information : MessageBoxIcon.Exclamation);
            isEdited = false;
            setSaveStatus(false);
        }

        private void btnDel_Click(object sender, EventArgs e)
        {
            if(lstViewDB.SelectedItems.Count > 0)
            {
                DialogResult dialogResult = MessageBox.Show($"是否删除 '{lstViewDB.SelectedItems[0].Text}' ？\n\n程序位置：\n{lstViewDB.SelectedItems[0].SubItems[1].Text}", Program.msgTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);

                if(dialogResult == DialogResult.Yes)
                {
                    int index = lstViewDB.SelectedItems[0].Index;
                    int imgIndex = lstViewDB.SelectedItems[0].ImageIndex;

                    DelFromImgList(imgIndex);

                    //lstViewDB.SelectedItems[0].Remove();
                    lstViewDB.Items[index].Remove();
                    for(int i = index; i < lstViewDB.Items.Count; ++i)
                    {
                        lstViewDB.Items[i].ImageIndex = i;
                    }

                    showCount();

                    ExeItems.RemoveAt(index);
                    for(int i = index - 1; i < ExeItems.Count; i++)
                    {
                        ExeItems[i].id = i;
                    }

                    setSaveStatus();
                }
            }
        }


        private void btnExit_Click(object sender, EventArgs e)
        {
            string msg = "是否退出？";
            if(isEdited)
            {
                msg = "修改内容未保存，是否退出？";
            }

            if(MessageBox.Show(this, msg, Program.msgTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                this.Dispose(true);
        }


        #region 右键菜单事件

        #region 查看菜单

        //重置查看菜单选中状态
        private void setMenuViewChecked(object sender)
        {
            if(sender.GetType() != toolMenuLarge.GetType())
                return;

            toolMenuLarge.Checked = false;
            toolMenuSmall.Checked = false;
            toolMenuList.Checked = false;
            toolMenuPing.Checked = false;

            ((ToolStripMenuItem)sender).Checked = true;
        }

        private void lstViewDB_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Right)
            {
                if(toolMenuView.DropDownItems.Count == 0)
                {
                    ToolStripItem[] items = new ToolStripItem[contextMenuView.Items.Count];
                    contextMenuView.Items.CopyTo(items, 0);
                    toolMenuView.DropDownItems.AddRange(items);
                }
            }
        }

        //大图标
        private void toolMenuLarge_Click(object sender, EventArgs e)
        {
            lstViewDB.LargeImageList = imgListLarge;
            lstViewDB.View = View.LargeIcon;
            lstViewDB.Alignment = ListViewAlignment.Top;

            setMenuViewChecked(sender);
        }

        //小图标
        private void toolMenuSmall_Click(object sender, EventArgs e)
        {
            lstViewDB.LargeImageList = lstViewDB.SmallImageList = imgList;
            lstViewDB.View = View.List;
            lstViewDB.Alignment = ListViewAlignment.Left;

            setMenuViewChecked(sender);
        }

        //列表
        private void toolMenuList_Click(object sender, EventArgs e)
        {
            lstViewDB.LargeImageList = lstViewDB.SmallImageList = imgListSmall;
            lstViewDB.View = View.Details;
            lstViewDB.Alignment = ListViewAlignment.Default;

            setMenuViewChecked(sender);
        }

        //平铺
        private void toolMenuPing_Click(object sender, EventArgs e)
        {
            lstViewDB.LargeImageList = lstViewDB.SmallImageList = imgList;

            //lstViewDB.TileSize = new Size((int)(lstViewDB.Width / 3.2), imgList.ImageSize.Height + 4);
            lstViewDB.TileSize = new Size(240, imgList.ImageSize.Height + 4);
            lstViewDB.View = View.Tile;
            lstViewDB.Alignment = ListViewAlignment.Default;

            setMenuViewChecked(sender);
        }

        #endregion 查看菜单

        #region 右键菜单

        private void contexMenu_Opening(object sender, CancelEventArgs e)
        {
            bool isSelected = lstViewDB.SelectedItems.Count > 0;
            toolMenuDel.Enabled = isSelected;
            toolMenuReName.Enabled = isSelected;
            toolMenuPropety.Enabled = isSelected;
            toolMenuOpenDir.Enabled = isSelected;
            toolMenuRun.Enabled = isSelected;
            toolMenuRunPropety.Enabled = isSelected;

            if(isSelected)
            {
                toolMenuRun.Image = (Image)imgListSmall.Images[lstViewDB.SelectedItems[0].ImageIndex].Clone();
                toolMenuRun.Text = $"启动 {lstViewDB.SelectedItems[0].Text}（&S）";
            }
            else
            {
                toolMenuRun.Image = picIcon.Image;
                toolMenuRun.Text = $"启动（&S）";
            }
        }

        private void toolMenuReName_Click(object sender, EventArgs e)
        {
            bool isSelected = lstViewDB.SelectedItems.Count > 0;
            if(isSelected)
            {
                string txt = lstViewDB.SelectedItems[0].Text;
                lstViewDB.SelectedItems[0].BeginEdit();
                setSaveStatus(txt == lstViewDB.SelectedItems[0].Text);

            }
        }

        private void toolMenuPropety_Click(object sender, EventArgs e)
        {
            if(lstViewDB.SelectedItems.Count == 1)
            {
                GameItem.ItemInfo itemInfo = getInfoFromItem(lstViewDB.SelectedItems[0]);
                GameItem.RunEXE(this, itemInfo, GameItem.RunType.Property);
            }
        }

        private void toolMenuOpenDir_Click(object sender, EventArgs e)
        {
            if(lstViewDB.SelectedItems.Count == 1)
            {
                GameItem.ItemInfo itemInfo = getInfoFromItem(lstViewDB.SelectedItems[0]);
                GameItem.RunEXE(this, itemInfo, GameItem.RunType.Directory);
            }
        }


        private void toolMenuRunPropety_Click(object sender, EventArgs e)
        {
            if(lstViewDB.SelectedItems.Count == 1)
            {
                var item = lstViewDB.SelectedItems[0];

                GameItem.ItemInfo itemInfo = getInfoFromItem(item);

                frmPropety frm = new frmPropety(itemInfo);

                var rtn = frm.ShowDialog(this);
                if(rtn == DialogResult.OK)
                {
                    itemInfo = frm.itemInfo;
                    EditListViewItem(itemInfo, item);
                    ExeItems[item.Index] = itemInfo;
                    setSaveStatus();
                }

                frm.Close();
                frm.Dispose();
            }

        }

        #endregion 右键菜单

        #endregion 右键菜单事件

        //启动选择的程序
        private void lstViewDB_DoubleClick(object sender, EventArgs e)
        {
            if(lstViewDB.SelectedItems.Count > 0)
            {
                GameItem.ItemInfo itemInfo = getInfoFromItem(lstViewDB.SelectedItems[0]);
                GameItem.RunEXE(this, itemInfo, GameItem.RunType.Executable, true);
            }
        }

        #region 拖放功能


        //交换2个ListViewItem的值
        private void swapItem(ListView lstView, int x, int y)
        {
            ListViewItem a = lstView.Items[x];
            ListViewItem b = lstView.Items[y];
            ListViewItem c = a.Clone() as ListViewItem;

            CopyItem(ref c, a);
            CopyItem(ref a, b);
            CopyItem(ref b, c);

            GameItem.ItemInfo item = ExeItems[x];
            int inxa = ExeItems[x].id;
            int inxb = ExeItems[y].id;
            ExeItems[x] = ExeItems[y];
            ExeItems[y] = item;

            ExeItems[x].id = x;
            ExeItems[y].id = y;

        }

        private void CopyItem(ref ListViewItem target, ListViewItem source)
        {
            target.Tag = source.Tag;
            target.Text = source.Text;
            target.ImageIndex = source.ImageIndex;
            target.ToolTipText = source.ToolTipText;
            for(int i = 0; i < source.SubItems.Count; i++)
            {
                target.SubItems[i].Text = source.SubItems[i].Text;
            }
        }

        /// <summary>
        /// 当拖动某项时触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstViewDB_ItemDrag(object sender, ItemDragEventArgs e)
        {
            //起动拖放放操作，设置拖放类型
            if(e.Button != MouseButtons.Left)
                return;

            lstViewDB.DoDragDrop(e.Item, DragDropEffects.Move | DragDropEffects.Scroll);
        }


        /// <summary>
        /// 鼠标拖动某项至该控件的区域
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstViewDB_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All | DragDropEffects.Move | DragDropEffects.Scroll;
        }

        /// <summary>
        /// 拖动时拖着某项置于某行上方时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstViewDB_DragOver(object sender, DragEventArgs e)
        {
            Point ptScreen = new(e.X, e.Y);
            Point pt = lstViewDB.PointToClient(ptScreen);
            ListViewItem item = lstViewDB.GetItemAt(pt.X, pt.Y);

            int colCount = lstViewDB.Width / lstViewDB.Items[0].ListView.GetItemRect(0).Width;
            if(lstViewDB.View == View.Details) colCount = 1;


            int index;
            if(item != null)
            {
                //int selH = item.ListView.GetItemRect(0).Size.Height; // 获取插入位置选项的矩形高度
                //int selY = item.Position.Y + selH / 2; // 计算插入位置选项的中心位置                

                if(lstViewDB.Height - pt.Y < 30 || lstViewDB.Width - pt.X < 30)
                {
                    index = item.Index + colCount;
                    if(index > lstViewDB.Items.Count) index = lstViewDB.Items.Count - 1;
                }
                else if(pt.Y < 20 || pt.X < 20)
                {
                    index = item.Index - (item.Index > 0 ? colCount : 0);
                }
                else
                    index = item.Index;

                item.Selected = true;
                lstViewDB.EnsureVisible(index);
            }

        }


        /// <summary>
        /// 处理拖进文件和图标拖动，结束拖动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstViewDB_DragDrop(object sender, DragEventArgs e)
        {
            if(e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                //拖动多个程序进行添加
                string[] files = (string[])(Array)e.Data.GetData(DataFormats.FileDrop);
                if(files.Length > 0)
                    AddFiles(files);
            }
            else
            {
                //移动图标排序                               
                Point ptScreen = new(e.X, e.Y);
                Point pt = lstViewDB.PointToClient(ptScreen);
                ListViewItem TargetItem = lstViewDB.GetItemAt(pt.X, pt.Y);//拖动的项将放置于该项之前   

                if(null == TargetItem)
                {
                    return;
                }

                ListViewItem draggedItem = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
                if(TargetItem == draggedItem)
                    return;

                int indexA = draggedItem.Index;
                int indexB = TargetItem.Index;

                if(indexA > indexB)
                {
                    for(int i = indexA; i > indexB; i--)
                        swapItem(lstViewDB, i, i - 1);

                }
                else
                {
                    for(int i = indexA; i < indexB; i++)
                        swapItem(lstViewDB, i, i + 1);

                }
            }

            setSaveStatus();
        }


        ListViewItem _Item = null;
        private void lstViewDB_MouseMove(object sender, MouseEventArgs e)
        {
            ListViewItem TargetItem = ((ListViewDBuf)sender).GetItemAt(e.X, e.Y);//拖动的项将放置于该项之前

            if(TargetItem == null || TargetItem == _Item)
                return;

            if(_Item == null)
                _Item = TargetItem;

            _Item.BackColor = Color.SkyBlue;
            TargetItem.BackColor = Color.FromArgb(255, 135, 253, 235);
            _Item = TargetItem;
        }

        #endregion 拖放功能


        private ListViewColumnSorter lvwColumnSorter = new();
        private void lstViewDB_ColumnClick(object sender, ColumnClickEventArgs e)
        {

            foreach(ColumnHeader ch in lstViewDB.Columns)
            {
                ch.ImageIndex = -1;
            }

            int index = e.Column;
            lstViewDB.ListViewItemSorter = lvwColumnSorter;

            if(index == lvwColumnSorter.SortColumn)
            {
                if(lvwColumnSorter.OrderOfSort == SortOrder.Ascending)
                {
                    lvwColumnSorter.OrderOfSort = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.OrderOfSort = SortOrder.Ascending;
                }
            }
            else
            {
                lvwColumnSorter.SortColumn = index;
                lvwColumnSorter.OrderOfSort = SortOrder.Ascending;
            }
            this.lstViewDB.Sort();
            lstViewDB.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);   //根据列的文本内容，自动设置list列的宽度
            lstViewDB.Update();
        }

        private void lstViewDB_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            bool isSelected = lstViewDB.SelectedItems.Count > 0;
            if(isSelected)
            {
                btnDelete.BackColor = Color.Empty;
            }
            else
            {
                btnDelete.BackColor = Color.LightGray;
            }
            btnDelete.Enabled = isSelected;
        }

        private void setSaveStatus(bool isEdit = true)
        {
            if(!isEdited)
                isEdited = isEdit;

            btnSave.Enabled = isEdited;

        }


        #region Apull标签事件

        private void lblApull_DoubleClick(object sender, EventArgs e)
        {
            ProcessStartInfo psi = new($"https://{lblApull.Text}/html/exestart.html");
            Process.Start(psi);
        }

        private void lblApull_MouseEnter(object sender, EventArgs e)
        {
            lblApull.ForeColor = Color.OrangeRed;
            lblApull.Cursor = Handcursor;
        }

        private void lblApull_MouseLeave(object sender, EventArgs e)
        {
            lblApull.ForeColor = Color.Navy;
        }

        #endregion

        #region 右上角最小化，最大化，还原按钮事件

        private void btnMin_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        private void btnMax_Click(object sender, EventArgs e)
        {
            this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height); //最大化不会全屏遮挡任务栏
            this.WindowState = (this.WindowState == FormWindowState.Normal) ? FormWindowState.Maximized : FormWindowState.Normal;
            btnMax.Image = (this.WindowState == FormWindowState.Maximized) ? Properties.Resources.reco : Properties.Resources.max;
        }

        private void panelTitle_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left && btnMax.Enabled)
                btnMax_Click(sender, e);
        }

        private void btnView_Click(object sender, EventArgs e)
        {
            if(contextMenuView.Items.Count == 0)
            {
                ToolStripItem[] items = new ToolStripItem[toolMenuView.DropDownItems.Count];
                toolMenuView.DropDownItems.CopyTo(items, 0);
                contextMenuView.Items.AddRange(items);
            }
            contextMenuView.Show((Button)sender, new Point(0, ((Button)sender).Height));
        }


        //处理快捷键
        private void FrmMain_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.F2 && lstViewDB.SelectedItems.Count > 0)
            {
                toolMenuReName_Click(sender, e);
            }
            else if(e.KeyCode == Keys.Escape)
                btnExit_Click(sender, e);
            else if(e.KeyCode == Keys.Enter)
                lstViewDB_DoubleClick(sender, e);
        }

        private void FrmMain_ResizeEnd(object sender, EventArgs e)
        {
            if(lstViewDB.View == View.Tile)
                toolMenuPing_Click(sender, e);
        }
        private void FrmMain_SizeChanged(object sender, EventArgs e)
        {
            if(WindowState == FormWindowState.Minimized) return;
        }


        private void btnAdd_MouseEnter(object sender, EventArgs e)
        {
            try
            {
                ((Button)sender).Cursor = Handcursor;
            }
            catch(Exception)
            {

            }
        }

        #endregion

        #region 任务栏图标

        /// <summary>
        /// 实现点击任务栏图标显示或隐藏窗体
        /// </summary>
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.Style = cp.Style | 0x20000;//允许最小化操作
                return cp;
            }
        }

        #endregion


    }


}
